package org.anachronos.jeep.probec.model;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.VariableElement;

import org.anachronos.jeep.probe.OnMethod;
import org.anachronos.jeep.probe.OnMethod.Kind;

public class ProbeMethod {
	private final String name;
	private final OnMethod.Kind kind;
	private final String[] interfaceNames;
	private final String methodPattern;
	private final String methodDescriptorPattern;
	private final List<ProbeArg> args = new ArrayList<ProbeArg>();
	
	public ProbeMethod(final String name, final Kind kind, final String[] interfaceNames,
			final String methodPattern, final String methodDescriptorPattern) {
		this.name = name;
		this.kind = kind;
		this.interfaceNames = interfaceNames;
		this.methodPattern = methodPattern;
		this.methodDescriptorPattern = methodDescriptorPattern;
	}

	public static ProbeMethod create(final ExecutableElement element) {
		final OnMethod onMethod = element.getAnnotation(OnMethod.class);
		final String name = element.getSimpleName().toString();
		final Kind kind = onMethod.kind();
		final String[] interfaceNames = onMethod.interfaceName();
		final String methodNamePattern = onMethod.methodName();
		final String methodDescriptiorPattern = onMethod.methodDescriptior();
		final ProbeMethod probeMethod = new ProbeMethod(name, kind, 
				interfaceNames, methodNamePattern, methodDescriptiorPattern);
		for(VariableElement parameterElement : element.getParameters()) {
			probeMethod.args.add(ProbeArg.create(parameterElement));
		}
		return probeMethod;
	}
	
	public boolean isEntry() {
		return Kind.ENTRY.equals(kind);
	}

	public boolean isExit() {
		return Kind.EXIT.equals(kind);
	}

	public String getName() {
		return name;
	}
	
	public String getGenClass() {
		final StringBuffer buffer = new StringBuffer().
			append(Character.toUpperCase(name.charAt(0))).append(name.substring(1));
		return buffer.toString();
	}

	public OnMethod.Kind getKind() {
		return kind;
	}

	public String[] getInterfaceNames() {
		return interfaceNames;
	}

	public String getMethodPattern() {
		return methodPattern;
	}

	public String getMethodDescriptorPattern() {
		return methodDescriptorPattern;
	}

	public List<ProbeArg> getArgs() {
		return args;
	}
	
	@Override
	public String toString() {
		return "ProbeMethod [name=" + name + ", kind=" + kind
				+ ", interfaceNames=" + Arrays.toString(interfaceNames)
				+ ", methodPattern=" + methodPattern
				+ ", methodDescriptorPattern=" + methodDescriptorPattern
				+ ", args=" + args + "]";
	}
}
